package com.pobox.tupletest;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import org.apache.log4j.Logger;

public class Tuple extends ArrayList<Item> implements Comparable<Tuple> {
    /**
     * Logger for this class
     */
    private static final Logger logger = Logger.getLogger(Tuple.class);

    private static final long serialVersionUID = 1L;
    private int inTestsCount;

    public Tuple() {
        super();
        inTestsCount = 0;
    }

    public Tuple(Tuple tuple) {
        super(tuple);
        inTestsCount = 0;
    }

    public int getInTestsCount() {
        logger.debug("getInTestsCount() - start");

        return inTestsCount;
    }

    public void setInTestsCount(int inTestsCount) {
        logger.debug("setInTestsCount(int) - start");

        this.inTestsCount = inTestsCount;
    }

    /**
     * @return true if this tuple is a subset of parameter tuple
     */
    public boolean isSubsetOfTuple(Tuple tuple) {
        logger.debug("isSubsetOfTuple(Tuple) - start");

        assert tuple != null : "tuple to test cannot be null";
        boolean returnboolean = tuple.containsAll(this);
        logger.debug("isSubsetOfTuple(Tuple) - end");
        return returnboolean;
    }

    /**
     * Override Equals -We want equality regardless of order which the
     * super.equals() treats as significant. As long as the Tuples are the same
     * size (have the same number of items) - create Sets for this and
     * otherTuples Items then return containsAll() of the two Sets.
     *
     * @param other
     *            another Object to copare this to
     * @return true or false iif this and other are equals, for our definition
     *         of equals
     */
    @Override
    public boolean equals(Object other) {
        logger.debug("equals(Object) - start");

        if (this == other) {
            logger.debug("equals(Object) - end");
            return true;
        }
        if (!(other instanceof Tuple)) {
            logger.debug("equals(Object) - end");
            return false;
        }
        Tuple otherTuple = (Tuple) other;
        if (this.size() != otherTuple.size()) {
            logger.debug("equals(Object) - end");
            return false;
        }
        Set<Item> thisSet = new HashSet<Item>(this);
        Set<Item> otherSet = new HashSet<Item>(otherTuple);
        boolean returnboolean = thisSet.containsAll(otherSet);
        logger.debug("equals(Object) - end");
        return returnboolean;
    }

    public String printTupleJennyStyle() {
        logger.debug("printTupleJennyStyle() - start");

        StringBuilder sb = new StringBuilder();
        for (Item item : this) {
            sb.append(" ");
            sb.append(item.getDimension());
            sb.append(item.getFeature());
        }
        String returnString = sb.toString();
        logger.debug("printTupleJennyStyle() - end");
        return returnString;
    }

    /**
     * @see java.lang.Comparable#compareTo(Object)
     */
    public int compareTo(Tuple otherTuple) {
        logger.debug("compareTo(Object) - start");

        final int BEFORE = -1;
        final int EQUAL = 0;
        final int AFTER = 1;

        if (this == otherTuple) {
            logger.debug("compareTo(Object) - end");
            return EQUAL;
        }
        if (this.size() < otherTuple.size()) {
            logger.debug("compareTo(Object) - end");
            return BEFORE;
        }
        if (this.size() > otherTuple.size()) {
            logger.debug("compareTo(Object) - end");
            return AFTER;
        }
        for (int i = 0; i < this.size(); i++) {
            int comparison = this.get(i).compareTo(otherTuple.get(i));
            if (comparison != EQUAL) {
                logger.debug("compareTo(Object) - end");
                return comparison;
            }
        }
        assert this.equals(otherTuple) : "compareTo inconsistent with equals.";

        logger.debug("compareTo(Object) - end");
        return EQUAL;
    }

}
